#!/usr/bin/python3
# -*- coding:utf-8 -*-
# @Time   :2021/12/23
# @Author :CJX
# @File   :remote_maintenance.py

import can
import time
import numpy as np
from Injection_valve import injection_port
from Injection_valve import insert_database
from dox_enquiry import dox_command
from detection_relay_board import di_status
from detection_relay_board import do_status
from sql_insert import sql_insert_err
from sql_insert import sql_insert_suc


def io_status():
    while 1:
        global var1, var2, data_do, data_di  # 类型为list
        global falling_edge, rising_edge
        global di_location, do_location, err_inquiry, var_err_inquiry
        # global edge, l_s_time  # 长按和短按判断，类型为array元素为True/False
        inquiry_do = can.Message(arbitration_id=0x0201, data=[0x01], is_extended_id=False)  # 问询
        bus.send(inquiry_do)  # 0x0201 DO状态 返回513
        message_do = bus.recv(timeout=1)  # 接收数据
        type_id_do = message_do.arbitration_id  # 返回can报文类型
        if type_id_do == 513:
            # time_float1 = message_do.timestamp          # 浮点数时间戳
            # time_date1 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(float(message_do.timestamp)))  # 转str时间
            # 取回4个字节,预留32通道,bytearray->int->bin(str)->去'0b'->bin->左补32位->反向排列
            data_do = '{:0>32b}'.format(int(bin(int.from_bytes(message_do.data[0:4], "little")).replace('0b', ''), 2))[
                      ::-1]
            # print(data_do, type(data_do))
            if var1 != data_do:  # 差异检测，差异写入数据库
                # write_sql(time_date1, type_id_do, data_do)+++++++++++注意排列顺序有修改
                var1 = data_do  # 给中间值赋新值
                do_location = list(data_do)
        time.sleep(0.1)

        err_inquiry = err_inquiry_function(8) + err_inquiry_function(11) + err_inquiry_function(12) + \
                      err_inquiry_function(23) + err_inquiry_function(24) + \
                      err_inquiry_function(25) + err_inquiry_function(26) + err_inquiry_function(27) + \
                      err_inquiry_function(28) + err_inquiry_function(29)
        # err_inquiry供dox_command函数使用，以免复位报警指令
        inquiry_di = can.Message(arbitration_id=0x0301, data=[0x01], is_extended_id=False)
        bus.send(inquiry_di)  # 0x0301  返回769/0x0301 di状态
        message_di = bus.recv(timeout=1)  # 接收数据
        type_id_di = message_di.arbitration_id  # 返回can报文类型
        if type_id_di == 769:
            # time_float2 = message_di.timestamp          # 浮点数时间戳
            # time_date2 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(float(message_di.timestamp)))  # 转str时间
            # 取回4个字,预留32通道,bytearray->int->bin(str)->去'0b'->bin->左补32位->反向排列
            data_di = '{:0>32b}'.format(int(bin(int.from_bytes(message_di.data[0:4], "little")).replace('0b', ''), 2))[
                      ::-1]
            # print(data_di, type(data_di))
            if data_di != var2:  # 差异检测，差异写入数据库
                # write_sql(time_date2, type_id_di, data_di)
                for k in range(32):
                    if var2[k] == '0' and data_di[k] == '1':  # 32点上升沿检测,没有检测到不复位
                        edge[0, k] = 1  # 写入边缘检测edge[0]
                        edge[1, k] = 0  # 复位下降沿
                        # time_diff[0, k] = time.time()  # 把时间写入array[0]，上升沿触发时间戳
                    if var2[k] == '1' and data_di[k] == '0':  # 32点下降沿检测,没有检测到不复位
                        edge[1, k] = 1  # 写入边缘检测edge[1]
                        edge[0, k] = 0  # 复位上升沿
                        # time_diff[1, k] = time.time()  # 把时间写入array[1]，下降沿触发时间戳
                    # l_s_time[0, k] = 0 < (time_diff[1, k] - time_diff[0, k]) < 3  # 短脉冲判断
                    # l_s_time[1, k] = 3 < (time_diff[1, k] - time_diff[0, k]) < 10  # 长脉冲判断
                    # print((time_diff[1, k] - time_diff[0, k]))
                var2 = data_di  # 给中间值赋新值
                di_location = list(data_di)  # 字符串转列表输出
                # print('下降沿', edge[1])
                # print('上升沿', edge[0])
                rising_edge = edge[0]
                falling_edge = edge[1]
        time.sleep(0.1)
        if di_location[0:1][0] == '1':
            break


def err_inquiry_function(err_num):  # 供dox_command函数使用，以免复位报警指令
    if do_location[err_num - 1:err_num][0] == "1":
        err_inquiry_num = [err_num]
    else:
        err_inquiry_num = [0]
    return err_inquiry_num


def remote_maintenance():  # 远程保养程序
    rm_n = 1
    ver = 0  # 1为带自动冲洗，0为不带自动冲洗
    remote_maintenance_t2 = 0
    remote_maintenance_t3 = 0
    while 1:
        global falling_edge, rising_edge, di_location
        global i2c_40, i2c_41, i2c_42, i2c_43, edge, err_inquiry
        remote_maintenance_t4 = 0
        remote_maintenance_t6 = 0
        remote_maintenance_t8 = 0
        remote_maintenance_t9 = 0
        remote_maintenance_t10 = 0
        if rm_n == 1:
            print("步骤1")
            dox_command([0], err_inquiry)  # 复位do
            injection_port(0)  # 切换阀复位,X-0指令
            time.sleep(3)
            if insert_database(0) == "004d":  # 查询指令
                rm_n = 2
                sql_insert_suc("切换阀初始化位置")
                pass  # 成功
            else:
                sql_insert_err("FX—0切换阀初始化故障")  # 可存入数据库
                dox_command([24], err_inquiry)
                return

        if rm_n == 2:
            print("步骤2")
            dox_command([21, 22], err_inquiry)  # 输出DO21,DO22
            rm_n = 3

        if rm_n == 3:
            print("步骤3")
            if ver == 0:
                rm_n = 7
            if ver == 1:
                rm_n = 4

        if rm_n == 4:
            print("步骤4")
            dox_command([9, 21, 22], err_inquiry)  # 输出DO9

            while remote_maintenance_t4 <= 29:  # 延时四十秒每秒检测一次di状态，状态符合就退出循环
                remote_maintenance_t4 = remote_maintenance_t4 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
                    break

            rm_n = 5

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
            break

        if rm_n == 5:
            print("步骤5")
            dox_command([2, 9, 22, 21], err_inquiry)  # 置位DO2
            t = 0
            while t <= 60:
                if di_location[2:3][0] == "1":
                    dox_command([9, 22, 21], err_inquiry)  # 复位DO2
                    injection_port(3)  # x-3指令
                    time.sleep(3)
                    if insert_database(0) == "034d":  # 查询指令
                        time.sleep(2)  # 延时两秒
                        rm_n = 6
                        sql_insert_suc("切换阀水冲洗位置")
                        pass  # 成功
                    else:
                        sql_insert_err("FX——3切换阀水冲洗位故障")  # 可存入数据库f-3
                        dox_command([24], err_inquiry)
                        return
                    t = 70
                    pass  # 输出检修状态
                else:
                    time.sleep(1)
                    t = t + 1
            if t > 70 and di_location[2:3][0] == "0":
                sql_insert_err("F-2检修指令故障")
                dox_command([23], err_inquiry)
                return  # 输出检修动作故障

        if rm_n == 6:
            print("步骤6")
            dox_command([3, 22, 21], err_inquiry)  # 复位DO9,输出DO3
            while remote_maintenance_t6 <= 24:  # 延时25秒每秒检测一次di状态，状态符合就退出循环
                remote_maintenance_t6 = remote_maintenance_t6 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
                    break
            rm_n = 7

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
            break

        if rm_n == 7:
            print("步骤7")
            dox_command([22, 21], err_inquiry)  # 复位DO3
            injection_port(2)  # x-2指令
            time.sleep(3)
            if insert_database(0) == "024d":  # 查询指令
                rm_n = 8
                sql_insert_suc("切换阀清洗位置")
            else:
                sql_insert_err("FX—3切换阀水冲洗位故障")  # 可存入数据库f-2
                dox_command([24], err_inquiry)
                return

        if rm_n == 8:
            print("步骤8")
            dox_command([4, 22, 21], err_inquiry)  # 输出DO4
            while remote_maintenance_t8 <= 7:  # 延时7秒每秒检测一次di状态，状态符合就退出循环
                remote_maintenance_t8 = remote_maintenance_t8 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
                    break
            rm_n = 9

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
            break

        if rm_n == 9:
            print("步骤9")
            dox_command([22, 21], err_inquiry)  # 复位DO4
            while remote_maintenance_t9 <= 299:  # 延时300秒每秒检测一次di状态，状态符合就退出循环
                remote_maintenance_t9 = remote_maintenance_t9 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
                    break
            rm_n = 10

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
            break

        if rm_n == 10:
            print("步骤10")
            dox_command([5, 22, 21], err_inquiry)  # 输出DO5
            while remote_maintenance_t10 <= 7:  # 延时7秒每秒检测一次di状态，状态符合就退出循环
                remote_maintenance_t10 = remote_maintenance_t10 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
                    break
            rm_n = 11

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
            break

        if rm_n == 11:
            print("步骤11")
            dox_command([22, 21], err_inquiry)  # 复位DO5
            while remote_maintenance_t3 < 20:  # t2计数，单位为天
                remote_maintenance_t2 = 0
                while remote_maintenance_t2 <= 86400:  # 一天的秒数
                    remote_maintenance_t2 = remote_maintenance_t2 + 1
                    time.sleep(1)
                    if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
                        break
                    remote_maintenance_t3 = remote_maintenance_t3 + 1
            rm_n = 12
        if di_location[0:1][0] == '0' or di_location[20:21][0] == '0':
            break

        if rm_n == 12:
            if remote_maintenance_t3 >= 20:
                rm_n = 10
                remote_maintenance_t3 = 0  # t2计数复位


if __name__ == "__main__":
    # message_di = 0
    global manual_control_status, remote_maintenance_status, automatic_cleaning_status, do_location
    global err_inquiry, var_err_inquiry, support_failure, err_inquiry_26
    global err_inquiry_27, err_inquiry_28, err_inquiry_29, err_inquiry_8, err_inquiry_12
    support_failure = 0  # 支架状态判断0
    var1, var2 = '00000000000000000000000000000000', '00000000000000000000000000000000'
    data_do, data_di = 0, 0
    var_err_inquiry = [0]
    err_inquiry = ['0', '0', '0', '0', '0', '0', '0', '0']
    err_inquiry_26 = ['0']
    err_inquiry_27 = ['0']
    err_inquiry_28 = ['0']
    err_inquiry_29 = ['0']
    err_inquiry_8 = ['0']
    err_inquiry_12 = ['0']
    do_location = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
                   '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
    di_location = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
                   '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
    falling_edge = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    rising_edge = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    edge = np.zeros(64, np.int8).reshape(2, 32)  # DI上升/下降沿检测,edge[0,0]第1个up，edge[1,0]第1个down
    time_diff = np.zeros(64, np.float64).reshape(2, 32)  # DI上升/下降沿的触发时间
    l_s_time = np.zeros(64, np.int8).reshape(2, 32)  # 短按判断l_s_time[0]|长按判断l_s_time[1]
    bus = can.Bus(interface='socketcan', channel='can0', receive_own_messages=eval('False'))
    while 1:
        for t in threads:
            t.start()
        for t in threads:
            t.join()
